﻿/*
* @Author: hong
* @Description:
* @Date: 2024年05月09日 星期四 17:05:23
* @Modify:
*/

using LocalizationUtils;
using TMPro;
using TMPro.EditorUtilities;
using UnityEditor;
using UnityEditor.Presets;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace LocalizationUtils.Editor
{
    public static class LocalizationTextHelp
    {
        #region TMP

        [MenuItem("GameObject/UI/LocalizationTMPText", false, 3001)]
        static void CreateLocalizationTextObjectPerform(MenuCommand menuCommand)
        {
            GameObject go = null;
#if UNITY_EDITOR
            go = ObjectFactory.CreateGameObject("LocalizeText (TMP)");
#else
            go = CreateUIElementRoot("Text (TMP)", new Vector2(100f, 100f));
#endif

            LocalizationTMPText textComponent = null;
#if UNITY_EDITOR
            textComponent = ObjectFactory.AddComponent<LocalizationTMPText>(go);
#else
            textComponent = go.AddComponent<LocalizationTMPText>();
#endif
            //// Override text color and font size
            // Apply TMP Settings Defaults if no Preset is defined
            if (Preset.GetDefaultForObject(textComponent) == null)
            {
                textComponent.fontSize = TMP_Settings.defaultFontSize;
                textComponent.color = Color.white;
                textComponent.text = "New Text";
            }

            if (TMP_Settings.autoSizeTextContainer)
            {
                Vector2 size = textComponent.GetPreferredValues(TMP_Math.FLOAT_MAX, TMP_Math.FLOAT_MAX);
                textComponent.rectTransform.sizeDelta = size;
            }
            else
            {
                textComponent.rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProUITextContainerSize;
            }

            PlaceUIElementRoot(go, menuCommand);
        }

        [MenuItem("GameObject/UI/LocalizationTMP3DText", false, 3001)]
        static void CreateLocalization3DTextObjectPerform(MenuCommand menuCommand)
        {
            GameObject go = null;
#if UNITY_EDITOR
            go = ObjectFactory.CreateGameObject("Localize3DText (TMP)");
#else
            go = CreateUIElementRoot("3DText (TMP)", new Vector2(100f, 100f));
#endif

            LocalizationTMP3DText textComponent = null;
#if UNITY_EDITOR
            textComponent = ObjectFactory.AddComponent<LocalizationTMP3DText>(go);
#else
            textComponent = go.AddComponent<LocalizationTMP3DText>();
#endif
            //// Override text color and font size
            // Apply TMP Settings Defaults if no Preset is defined
            if (Preset.GetDefaultForObject(textComponent) == null)
            {
                textComponent.fontSize = TMP_Settings.defaultFontSize;
                textComponent.color = Color.white;
                textComponent.text = "New 3DText";
            }

            if (TMP_Settings.autoSizeTextContainer)
            {
                Vector2 size = textComponent.GetPreferredValues(TMP_Math.FLOAT_MAX, TMP_Math.FLOAT_MAX);
                textComponent.rectTransform.sizeDelta = size;
            }
            else
            {
                textComponent.rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProUITextContainerSize;
            }

            PlaceUIElementRoot(go, menuCommand);
        }

        private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)
        {
            GameObject parent = menuCommand.context as GameObject;
            bool explicitParentChoice = true;
            if (parent == null)
            {
                parent = TMPro_CreateObjectMenu.GetOrCreateCanvasGameObject();
                explicitParentChoice = false;

                // If in Prefab Mode, Canvas has to be part of Prefab contents,
                // otherwise use Prefab root instead.
                PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
                if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent))
                    parent = prefabStage.prefabContentsRoot;
            }

            if (parent.GetComponentInParent<Canvas>() == null)
            {
                // Create canvas under context GameObject,
                // and make that be the parent which UI element is added under.
                GameObject canvas = TMPro_CreateObjectMenu.CreateNewUI();
                canvas.transform.SetParent(parent.transform, false);
                parent = canvas;
            }

            // Setting the element to be a child of an element already in the scene should
            // be sufficient to also move the element to that scene.
            // However, it seems the element needs to be already in its destination scene when the
            // RegisterCreatedObjectUndo is performed; otherwise the scene it was created in is dirtied.
            SceneManager.MoveGameObjectToScene(element, parent.scene);

            if (element.transform.parent == null)
            {
                Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name);
            }

            GameObjectUtility.EnsureUniqueNameForSibling(element);

            // We have to fix up the undo name since the name of the object was only known after reparenting it.
            Undo.SetCurrentGroupName("Create " + element.name);

            GameObjectUtility.SetParentAndAlign(element, parent);
            if (!explicitParentChoice) // not a context click, so center in sceneview
                SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(),
                    element.GetComponent<RectTransform>());

            Undo.RegisterCreatedObjectUndo(element, "Create " + element.name);

            Selection.activeGameObject = element;
        }

        private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform,
            RectTransform itemTransform)
        {
            // Find the best scene view
            SceneView sceneView = SceneView.lastActiveSceneView;
            if (sceneView == null && SceneView.sceneViews.Count > 0)
                sceneView = SceneView.sceneViews[0] as SceneView;

            // Couldn't find a SceneView. Don't set position.
            if (sceneView == null || sceneView.camera == null)
                return;

            // Create world space Plane from canvas position.
            Camera camera = sceneView.camera;
            Vector3 position = Vector3.zero;
            Vector2 localPlanePosition;

            if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform,
                    new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition))
            {
                // Adjust for canvas pivot
                localPlanePosition.x =
                    localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
                localPlanePosition.y =
                    localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;

                localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
                localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);

                // Adjust for anchoring
                position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
                position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;

                Vector3 minLocalPosition;
                minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) +
                                     itemTransform.sizeDelta.x * itemTransform.pivot.x;
                minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) +
                                     itemTransform.sizeDelta.y * itemTransform.pivot.y;

                Vector3 maxLocalPosition;
                maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) -
                                     itemTransform.sizeDelta.x * itemTransform.pivot.x;
                maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) -
                                     itemTransform.sizeDelta.y * itemTransform.pivot.y;

                position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
                position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
            }

            itemTransform.anchoredPosition = position;
            itemTransform.localRotation = Quaternion.identity;
            itemTransform.localScale = Vector3.one;
        }

        #endregion

        #region UGUI

        [MenuItem("GameObject/UI/LocalizationUGUIText", false, 3001)]
        static void CreateLocalizationUGUITextObjectPerform(MenuCommand menuCommand)
        {
            GameObject go = null;
#if UNITY_EDITOR
            go = ObjectFactory.CreateGameObject("LocalizeText (UGUI)");
#else
            go = CreateUIElementRoot("LocalizeText (UGUI)", new Vector2(100f, 100f));
#endif

            LocalizationUGUIText textComponent = null;
#if UNITY_EDITOR
            textComponent = ObjectFactory.AddComponent<LocalizationUGUIText>(go);
#else
            textComponent = go.AddComponent<LocalizationUGUIText>();
#endif

            PlaceUIElementRoot(go, menuCommand);
        }

        /*[MenuItem("GameObject/UI/LocalizationUGUIText - InputField", false, 3002)]
        static void CreateLocalizationUGUITextInputFieldObjectPerform(MenuCommand menuCommand)
        {
        }*/

        [MenuItem("GameObject/UI/LocalizationUGUIText - RegexHyperLinkText", false, 3001)]
        static void CreateRegexHyperLinkTextObjectPerform(MenuCommand menuCommand)
        {
            GameObject go = null;
#if UNITY_EDITOR
            go = ObjectFactory.CreateGameObject("RegexHyperLinkText (UGUI)");
#else
            go = CreateUIElementRoot("RegexHyperLinkText (UGUI)", new Vector2(100f, 100f));
#endif

            RegexHyperLinkUGUIText textComponent = null;
#if UNITY_EDITOR
            textComponent = ObjectFactory.AddComponent<RegexHyperLinkUGUIText>(go);
#else
            textComponent = go.AddComponent<RegexHyperLinkUGUIText>();
#endif

            PlaceUIElementRoot(go, menuCommand);
        }

        #endregion
    }
}